/**
 * canvas2d_tests.js
 * 
 * Some 2D canvas experimentation stuff.
 * 
 * @author A.Weissflog
 *
 * (C) 2010 A.Weissflog
 */

var FrameCount = 0;
var EyePos = Float4.FromValues(0.0, 0.0, 10.0, 1.0);
var LookatPos  = Float4.FromValues(0.0, 0.0, 0.0, 1.0);
var UpVec  = Float4.FromValues(0.0, 1.0, 0.0, 0.0);
var ViewMatrix = Matrix44.LookatRh(EyePos, LookatPos, UpVec);
var ProjMatrix = Matrix44.PerspFovRh(Scalar.Deg2Rad(70.0), 1.0, 0.1, 100.0);

/**
 * Draw a cube to a canvas 2d context
 * @param {Object} ctx
 * @param {Float4} pos
 * @param {Matrix44} mvpMatrix
 */
function DrawCube(ctx, canvasWidth, canvasHeight, pos, mvpMatrix)
{
    // compute corner points
	var srcCorners = [8];	
	srcCorners[0] = Float4.Add(pos, Float4.FromValues(-0.5, -0.5, -0.5, 0.0));
	srcCorners[1] = Float4.Add(pos, Float4.FromValues(+0.5, -0.5, -0.5, 0.0));
	srcCorners[2] = Float4.Add(pos, Float4.FromValues(+0.5, +0.5, -0.5, 0.0));
	srcCorners[3] = Float4.Add(pos, Float4.FromValues(-0.5, +0.5, -0.5, 0.0));
    srcCorners[4] = Float4.Add(pos, Float4.FromValues(-0.5, -0.5, +0.5, 0.0));
    srcCorners[5] = Float4.Add(pos, Float4.FromValues(+0.5, -0.5, +0.5, 0.0));
    srcCorners[6] = Float4.Add(pos, Float4.FromValues(+0.5, +0.5, +0.5, 0.0));
    srcCorners[7] = Float4.Add(pos, Float4.FromValues(-0.5, +0.5, +0.5, 0.0));
	
	// project corners into post-projected space
	var projCorners = [8];
	for (var i = 0; i < 8; i++)	
	{
		projCorners[i] = Matrix44.Transform(srcCorners[i], mvpMatrix);
 		projCorners[i].x = ((projCorners[i].x / projCorners[i].w) + 0.5) * canvasWidth;
        projCorners[i].y = ((projCorners[i].y / projCorners[i].w) + 0.5) * canvasHeight;
        projCorners[i].z /= projCorners[i].w;		
	}

    // draw cube to canvas
	ctx.beginPath();

	ctx.moveTo(projCorners[0].x, projCorners[0].y);
	ctx.lineTo(projCorners[1].x, projCorners[1].y);
	ctx.lineTo(projCorners[2].x, projCorners[2].y);
	ctx.lineTo(projCorners[3].x, projCorners[3].y);
	ctx.lineTo(projCorners[0].x, projCorners[0].y);

    ctx.moveTo(projCorners[4].x, projCorners[4].y);
    ctx.lineTo(projCorners[5].x, projCorners[5].y);
    ctx.lineTo(projCorners[6].x, projCorners[6].y);
    ctx.lineTo(projCorners[7].x, projCorners[7].y);
    ctx.lineTo(projCorners[4].x, projCorners[4].y);

	ctx.moveTo(projCorners[0].x, projCorners[0].y);
	ctx.lineTo(projCorners[4].x, projCorners[4].y);
	ctx.moveTo(projCorners[1].x, projCorners[1].y);
	ctx.lineTo(projCorners[5].x, projCorners[5].y);
	ctx.moveTo(projCorners[2].x, projCorners[2].y);
	ctx.lineTo(projCorners[6].x, projCorners[6].y);
	ctx.moveTo(projCorners[3].x, projCorners[3].y);
	ctx.lineTo(projCorners[7].x, projCorners[7].y);

	ctx.stroke();
}

function DrawFrame()
{
	var canvas = document.getElementById("canvas");
	var ctx = canvas.getContext("2d");
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	
	// compute view matrix 
    var curEyePos = Float4.FromValues(Math.sin(FrameCount * 0.1) * 10.0, Math.sin(FrameCount * 0.02) * 5.0, Math.cos(FrameCount * 0.1) * 10, 1.0);
	var viewMatrix = Matrix44.Inverse(Matrix44.LookatRh(curEyePos, LookatPos, UpVec));	
	
    for (x = -5; x < +5; x++)
	{
		for (y = -5; y < +5; y++)
		{
			for (z = -5; z < +5; z++) 
			{
				var modelMatrix = Matrix44.RotationYawPitchRoll(FrameCount * 0.1, FrameCount * 0.2, FrameCount * 0.05);
				modelMatrix.Scale(0.2);
				modelMatrix.Translate(x * 0.25, y * 0.25, z * 0.25);
				
				// setup model view projection matrix
				var modelViewMatrix = Matrix44.Multiply(modelMatrix, viewMatrix);
				var mvpMatrix = Matrix44.Multiply(modelViewMatrix, ProjMatrix);
				
				// render a cube at the origin
				var pos = Float4.FromValues(0.0, 0.0, 0.0, 1.0);
				DrawCube(ctx, canvas.width, canvas.height, pos, mvpMatrix);
			}
		}		
	}
	
    FrameCount++;
}
